package cn.agiledata.bank.barcodepayment.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.agiledata.bank.barcodepayment.dao.BarCodePayCorpDao;
import cn.agiledata.bank.barcodepayment.dao.BarCodePayDetailDao;
import cn.agiledata.bank.barcodepayment.dao.BarCodePayTypeDao;
import cn.agiledata.bank.barcodepayment.exception.BarCodePayException;
import cn.agiledata.bank.barcodepayment.form.BarCodePayForm;
import cn.agiledata.bank.barcodepayment.form.PayHistoryQueryPageList;
import cn.agiledata.bank.barcodepayment.logic.BarCode;
import cn.agiledata.bank.common.dao.AccountTemplate;
import cn.agiledata.bank.common.dao.TransactionTemplate;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.common.util.MD5;
import cn.agiledata.bank.common.util.PageBean;
import cn.agiledata.bank.common.util.UniqueIdentityUtil;
import cn.agiledata.bank.common.util.WeatherUtil;
import cn.agiledata.bank.facade.helper.NotificationHelper;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.BarCodePayCorp;
import cn.agiledata.bank.hibernateBean.BarCodePayDetail;
import cn.agiledata.bank.hibernateBean.BarCodePayType;
import cn.agiledata.bank.hibernateBean.Transaction;

public class BarCodePayServiceImpl implements BarCodePayService {

    private BarCodePayTypeDao barCodePayTypeDao;

    private BarCodePayCorpDao barCodePayCorpDao;
    
    private BarCodePayDetailDao barCodePayDetailDao;

    private Map barCodeMapping;
    
    private TransactionTemplate transactionTemplate;
    
    private AccountTemplate accountTemplate;
    
    private NotificationHelper notificationHelper;// 邮件发送服务

	public NotificationHelper getNotificationHelper() {
		return notificationHelper;
	}

	public void setNotificationHelper(NotificationHelper notificationHelper) {
		this.notificationHelper = notificationHelper;
	}

	public void setAccountTemplate(AccountTemplate accountTemplate) {
		this.accountTemplate = accountTemplate;
	}

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	public void setBarCodePayDetailDao(BarCodePayDetailDao barCodePayDetailDao) {
		this.barCodePayDetailDao = barCodePayDetailDao;
	}

	public void setBarCodePayCorpDao(BarCodePayCorpDao barCodePayCorpDao) {
        this.barCodePayCorpDao = barCodePayCorpDao;
    }

    public void setBarCodePayTypeDao(BarCodePayTypeDao barCodePayTypeDao) {
        this.barCodePayTypeDao = barCodePayTypeDao;
    }

    public void setBarCodeMapping(Map barCodeMapping) {
        this.barCodeMapping = barCodeMapping;
    }

    public List getBarCodePayTypes() {
        return barCodePayTypeDao.getBarCodePayTypes();
    }

    public List getBarCodePayCorpsByType(Long type) {
        List list =  barCodePayCorpDao.getBarCodePayCorpsByType(type);
        return list;
    }

    public BarCode getBarCode(String corpCode, String barCodeValue)
            throws BarCodePayException {
        BarCode barCode = (BarCode) this.barCodeMapping.get(corpCode);
        if (barCode == null) {
            throw BarCodePayException.ERROR_CORPCODE;
        }
        barCode.setValue(barCodeValue);
        return barCode;
    }
    
   
    
    public String getBarCodePayFeeNo(){
    	return UniqueIdentityUtil.getBarCodePayFeeNo();
    }
    
    public BarCodePayDetail getBarCodePayDetailByCode(String code) {
    	return barCodePayDetailDao.unLogHistoryDetail(code);
    }

	public BarCodePayDetail getNewBarCodePayDetail(BarCodePayForm form,
			Account account, Date chargeDate) throws BarCodePayException {

		// 查询未付款的条形码
		BarCodePayDetail detail = barCodePayDetailDao.unLogHistoryDetail(form
				.getCode());
		
		if(detail == null) {
			// 未查询到未付款的相同条码记录，新建
			detail = new BarCodePayDetail();
		}
		else {
			// 如果已经完成付款，抛出异常
			if(detail.getPayfeeStatus().equals(Constant.USER_BARCODEPAY_STATUS_PAYED)) {
				throw BarCodePayException.ERROR_FEEPAYED;
			}
		}
			
		detail.setAmount(form.getAmount().doubleValue());
		detail.setBarCode(form.getCode());
		BarCodePayCorp corp = barCodePayCorpDao.getBarCodePayCorpsByCode(form.getCorpCode());
		detail.setBarCodePayCorp(corp);
		detail.setChargeDate(DateUtil.string2Date(form.getDate()));
		detail.setPayFeeDate(new Date());
		detail.setPayfeeStatus(Constant.USER_BARCODEPAY_STATUS_WAITPAY);
		detail.setChargeDate(chargeDate);
		detail.setPersonName(form.getPersonName());
		detail.setMobile(form.getMobile());
		detail.setEmail(form.getEmail());
		
		String updateUser = "SYSTEM";
		if(account!=null){
			updateUser = account.getId().toString();
			detail.setAccount(account);
		}
		detail.setPayFeeNo(form.getPayFeeNo());
		WeatherUtil.fillCreateAndUpdateInfo(detail, updateUser);
		return detail;
	}

	public void saveBarCodePayDetail(BarCodePayDetail detail){
		barCodePayDetailDao.saveBarCodePayDetail(detail);
	}

	public void updateBarCodePayDetail(BarCodePayDetail detail){
		barCodePayDetailDao.updateBarCodePayDetail(detail);
	}
	
	public BarCodePayCorp getBarCodePayCorpsByCode(String code){
		return barCodePayCorpDao.getBarCodePayCorpsByCode(code);
	}

	public BarCodePayDetail getBarCodePayDetailByPayFeeNo(String feeCodeNo) {
		
		return barCodePayDetailDao.getBarCodePayDetailByPayFeeNo(feeCodeNo);
	}

	public BarCodePayType getBarCodePayTypeById(Long id) {
		return barCodePayTypeDao.getBarCodePayTypeById(id);
	}
	
	public BarCodePayDetail getPayedBarCodePayDetail(BarCodePayDetail detail,String transId){
		detail.setPayfeeStatus(Constant.USER_BARCODEPAY_STATUS_PAYED);
		
		Transaction trans = transactionTemplate.getTransactionByTranId(transId);
		Account account = trans.getDebit().getAccount();
		
		if(!Constant.ACCOUNT_TYPE_INITIAL.equals(account.getAccountType())){
			detail.setAccount(trans.getDebit().getAccount());
		}
		detail.setTransaction(trans);
		WeatherUtil.fillCreateAndUpdateInfo(detail, trans.getUpdateUser());
		
		return detail;
	}
	//查询缴费历史
	public PageBean getPayHistory(BarCodePayForm form) {
		PayHistoryQueryPageList pageList = new PayHistoryQueryPageList(form) ;
		
		return pageList.getAccountListPageBean();
	}
	
	public boolean ifFeePayed(String barcode){
		List list = barCodePayDetailDao.getBarCodePayDetail(barcode, Constant.USER_BARCODEPAY_STATUS_PAYED);
		return list.size() >0;
	}

	public boolean ifDataExtended(Date data) {
		Date now  = new Date();
		int days = DateUtil.naturalDaysBetween(data, now);
		return (days>60 || days < 0);
	}

	public void sendNotify(BarCodePayDetail detail) {
		
		String strEmail = null;
		String strMobile = null;
		String strName = "";
		
		if(detail.getAccount() != null) {
			// 用户登录后缴费，使用用户相关信息进行通知
			Account account = accountTemplate.getAccount(detail.getAccount()
					.getId().toString());
			
			strEmail = account.getEmail();
			strMobile = account.getMobile();
			if(account.getName() != null) {
				strName = account.getName();
			}
		}
		else {
			strEmail = detail.getEmail();
			strMobile = detail.getMobile();
			strName = detail.getPersonName();
		}
		
		if(strEmail != null && strEmail.trim().length() > 0) {
			// Mail不为空
			String strSubject = "您的公共事业缴费通知";
			Map context = new HashMap();
			if(strName == null || strName.trim().length()== 0) {
				strName = "用户";
			}
			context.put("userName", strName);
			context.put("type", detail.getBarCodePayCorp().getBarCodePayType().getName());
			context.put("transNo", detail.getTransaction().getTransId());
			context.put("time", DateUtil.date2String(new Date()));
			context.put("company", detail.getBarCodePayCorp().getName());
			context.put("barcode", detail.getBarCode());
			context.put("amount", String.valueOf(detail.getAmount()));
			context.put("sendTime", DateUtil.date2String(new Date()));
			context.put("chargeDate", DateUtil.date2String(detail.getChargeDate(),"yyyy-MM"));
			
			notificationHelper.sendEmail(strEmail, strSubject, "mail-publicFee.vm", context);
		}
		
		if(strMobile != null && strMobile.trim().length() > 0) {
			// 手机不为空
			Map context = new HashMap();
			context.put("time", DateUtil.date2String(new Date()));
			context.put("type", detail.getBarCodePayCorp().getBarCodePayType().getName());
			context.put("amount", String.valueOf(detail.getAmount()));
			String strTransId = detail.getTransaction().getTransId().trim();
			context.put("transNo",strTransId.substring(strTransId.length() - 4));
			notificationHelper.sendPublicFeeSms(strMobile,context);
		}
		
	}
	
	/**
	 * 根据缴费明细信息计算验证签名
	 * 
	 * @param detail
	 * @return
	 */
	public String generateMac(BarCodePayDetail detail) {
		// 组成验证签名明文
		StringBuffer sbDetail = new StringBuffer();
		sbDetail.append("transId=").append(detail.getTransaction().getTransId());	// 交易编号
		sbDetail.append("barCode=").append(detail.getBarCode());		// 条形码
		sbDetail.append("amount=").append(detail.getAmount());
		sbDetail.append("company=").append(detail.getBarCodePayCorp().getCode());
		
		String mac = new MD5().getMD5ofStr(sbDetail.toString());
		return mac;
	}

	public BarCodePayDetail paySuccess(String orderId, String transId) {
		BarCodePayDetail detail = getBarCodePayDetailByPayFeeNo(orderId);
		if (Constant.USER_BARCODEPAY_STATUS_WAITPAY.equals(detail.getPayfeeStatus())) {
			// 未完成通知，进行状态更新
			detail = getPayedBarCodePayDetail(detail, transId);
			saveBarCodePayDetail(detail);

			sendNotify(detail);
		}
		
		return detail;
	}
}
